# Copyright (C) Infiscape Corporation 2006
import sys, os, os.path, time, traceback, math
pj = os.path.join

from PyQt4 import QtGui, QtCore, QtOpenGL

import osg2

import lucid.core
from pydispatch import dispatcher

class OurDockWidget(QtGui.QDockWidget):
   def __init__(self, parent=None, flags=QtCore.Qt.WindowFlags()):      
      title = ""
      QtGui.QDockWidget.__init__(self, title, parent, flags)
      self.mContextMenu = QtGui.QMenu(self)
      self.mViewMenu = self.mContextMenu.addMenu("Add view...")
      self.mContextMenu.addSeparator()
      self.mContextMenu.addAction("Remove tab",self.removeTab)
      
      self.setObjectName("dock_widget-%s"%id(self))
      self.setupWidget()
      
      # View settings
      self.mActiveViewPlugins = []  # list of [plugin_type_name, plugin_inst, view widget]
      self.mViewPluginCalls = {}    # Map: plugin_type_name --> creation call
      env = lucid.core.Environment()
      for (type_name,p) in env.mViewPluginsHolder.mViewPlugins.iteritems():
         view_name = p.getName()
         view_call = lambda pname=type_name: self.addView(pname)
         action = self.mViewMenu.addAction(view_name, view_call)
         self.mViewPluginCalls[type_name] = view_call
      
      # Setup context menu
      self.tabWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
      self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
      self.connect(self.tabWidget, 
                   QtCore.SIGNAL("customContextMenuRequested(QPoint)"),
                   self.onContextMenu)
      self.connect(self, 
                   QtCore.SIGNAL("customContextMenuRequested(QPoint)"),
                   self.onContextMenu)
      
      #self.connect(self.toolButton, QtCore.SIGNAL("pressed()"), self.onContextMenu)
      self.toolButton.connect(self.toolButton, QtCore.SIGNAL("pressed()"), self.onContextMenu)
      
      self.connect(self, QtCore.SIGNAL("topLevelChanged(bool)"), self.updateTabPosition)
      self.connect(self, QtCore.SIGNAL("allowedAreasChanged()"), self.updateTabPosition)
   
   def setupWidget(self):
      # Copy code from dock_widget_sandbox.py
      self.dockWidgetContents = QtGui.QWidget(self)
      self.dockWidgetContents.setObjectName("dockWidgetContents")

      self.vboxlayout1 = QtGui.QVBoxLayout(self.dockWidgetContents)
      self.vboxlayout1.setMargin(0)
      self.vboxlayout1.setSpacing(0)
      self.vboxlayout1.setObjectName("vboxlayout1")

      self.tabWidget = QtGui.QTabWidget(self.dockWidgetContents)
      self.tabWidget.setTabPosition(QtGui.QTabWidget.North)
      self.tabWidget.setTabShape(QtGui.QTabWidget.Rounded)
      self.tabWidget.setObjectName("tabWidget")
      
      self.toolButton = QtGui.QToolButton(self.tabWidget)
      #self.toolButton = QtGui.QToolButton()
      self.toolButton.setAutoRaise(True)
      self.toolButton.setArrowType(QtCore.Qt.DownArrow) 
      
      if 1:
         # XXX: This will work in Qt 4.2 for all tab layout locations
         self.tabWidget.setCornerWidget(self.toolButton, QtCore.Qt.TopRightCorner)
      else:
         self.toolButton.setParent(self.vboxlayout1)
         self.vboxlayout1.addWidget(self.toolButton)

      self.tab = QtGui.QWidget()
      self.tab.setObjectName("tab")
      self.tabWidget.addTab(self.tab, "")      

      # Custom
      #self.vboxlayout1.addWidget(self.toolButton)
      self.vboxlayout1.addWidget(self.tabWidget)
      self.setWidget(self.dockWidgetContents)      


   def closeEvent(self, event):
      self.emit(QtCore.SIGNAL("pyDockableClosing"), self)
      QtGui.QDockWidget.closeEvent(self, event)
   
   def addView(self, pluginTypeName):
      """ Add a new view with the given plugin name.
          If we fail, display the reason why so the user will know.
      """
      # Try to get the plugin
      env = lucid.core.Environment()
      vtype = env.mViewPluginsHolder.mViewPlugins.get(pluginTypeName,None)
      if not vtype:
         warning_text = "Warning: could not find view plugin of name: %s"%pluginTypeName      
         print warning_text
         QtGui.QMessageBox.critical(self, "Plugin Failure", warning_text, 
                                    QtGui.QMessageBox.Ignore|QtGui.QMessageBox.Default|QtGui.QMessageBox.Escape,
                                    QtGui.QMessageBox.NoButton, QtGui.QMessageBox.NoButton)
         return
      view_name = vtype.getName()
      
      # Try to load the view
      new_view = None
      try:
         print "Creating new view: %s %s"%(pluginTypeName, vtype.__name__)
         new_view = vtype()
         new_view_widget = new_view.getViewWidget()         
         tab_icon = new_view.getIcon()
         if tab_icon:
            self.tabWidget.addTab(new_view_widget, tab_icon, view_name)
         else:
            self.tabWidget.addTab(new_view_widget, view_name)
         self.mActiveViewPlugins.append([pluginTypeName,new_view, new_view_widget])
      except Exception, ex:
         view_name = "Unknown"
         if vtype:
            view_name = vtype.getName()
         if new_view and new_view.getViewWidget():
            new_view.getViewWidget().destroy()
            new_view = None
         err_text = "Error loading view:" + view_name + "\n  exception:" + str(ex)
         print err_text
         traceback.print_exc()
         
         QtGui.QMessageBox.critical(self, "Plugin Failure", err_text, 
                                    QtGui.QMessageBox.Ignore|QtGui.QMessageBox.Default|QtGui.QMessageBox.Escape,
                                    QtGui.QMessageBox.NoButton, QtGui.QMessageBox.NoButton)

   def removeTab(self):
      """ Called when the current tab should be removed. """
      cur_tab = self.tabWidget.currentIndex()
      cur_widget = self.tabWidget.widget(cur_tab)
      self.tabWidget.removeTab(cur_tab)

      assert self.mActiveViewPlugins[cur_tab][2] == cur_widget
      del self.mActiveViewPlugins[cur_tab]
      

   def onContextMenu(self):
      print "Context menu"      
      self.mContextMenu.exec_(QtGui.QCursor.pos())      
   
   def updateTabPosition(self):
      print "Update tab position"
      return
      
      # Skip for now until we can get the tool bar working everywhere
      dock_pos = self.parent().dockWidgetArea(self)
      
      if QtCore.Qt.LeftDockWidgetArea == dock_pos:
         self.tabWidget.setTabPosition(QtGui.QTabWidget.East)
      elif QtCore.Qt.RightDockWidgetArea == dock_pos:
         self.tabWidget.setTabPosition(QtGui.QTabWidget.West)
      elif QtCore.Qt.TopDockWidgetArea == dock_pos:
         self.tabWidget.setTabPosition(QtGui.QTabWidget.South)
      elif QtCore.Qt.BottomDockWidgetArea == dock_pos:
         self.tabWidget.setTabPosition(QtGui.QTabWidget.North)
      else:
         print "Error: Invalid dock pos, could not find dock."
   
   def saveState(self):
      """ Return an object representing the state of this dock. """
      state = {}
      active_plugins = []
      for p in self.mActiveViewPlugins:
         active_plugins.append(p[0])
      state["active_plugins"] = active_plugins
      state["name"] = str(self.objectName())
      return state
   
   def loadState(self, state):
      """ Load the state of this object from the state object. """
      active_plugins = state.get("active_plugins",None)
      if not active_plugins:
         print "Warning: dock widget state missing 'active_plugins'."
      else:
         # If we have plugins, remove the current tab
         if len(active_plugins) > 0 and self.tabWidget.count() > 0:
            self.tabWidget.removeTab(0)
            
         for n in active_plugins:
            self.addView(n)
      obj_name = state.get("name",None)
      if obj_name:
         self.setObjectName(obj_name)
      


